#include <stdio.h>
#include <signal.h>
#include "console.h"
#include "t_types.h"
#include "hal/hal_audio.h"
#include "hal/hal_uart.h"
#include "hal/imx6/src/hal_mcu.h"
#include "pal/protocol_rsu.h"
#include "userLog.h"
#include <unistd.h>
#include <assert.h>
#include "CxlUtil.h"
#include "pal/laneLibuv.h"
#include "pal/vzCmdAdd.h"
#include "pal/vz_app.h"
#include "pal/lane_control.h"
#include "uv.h"
#include "common/pidfile.h"
#include <stdlib.h>
#include <string.h>
#include "common/configParser.h"
#include "pal/lane_cmd_parse_fn.h"
#include "hal/imx6/src/hal_gps_uv.h"
#include "pending_data_queue.h"
#include "hal/imx6/src/hal_gps_libuv.h"
#include "sqlLoop.h"
#include "picDeleteLoop.h"
#include "vzLibuv.h"

// #define CRITERION

void show_logo(void)
{
	LOG_INFO("#################################################");
	LOG_INFO("################# Welcom To Tim #################");
	LOG_INFO("#################################################");
	LOG_INFO("Version:0.8");
	LOG_INFO("修改内容：1、心跳增加gps信息  2、修改上传心跳的机制");
	LOG_INFO("Build:%s %s", __DATE__, __TIME__);
}

void handle_pipe(int sig)
{
	//不做任何处理即可
	LOG_WARN("ingore signalId=%d\n", sig);
	return;
}

void handle_sevg(int32_t sig)
{
	LOG_WARN("捕捉信号=%d", sig);
	bt();
	abort();
}

// int init_lxf()
// {
// 	//////////////
// 	//在linux下写socket的程序的时候，如果尝试send到一个disconnected socket上，就会让底层抛出一个SIGPIPE信号。
// 	//	这个信号的缺省处理方法是退出进程，大多数时候这都不是我们期望的。因此我们需要重载这个信号的处理方法。
// 	//调用以下代码，即可安全的屏蔽SIGPIPE：
// 	//signal设置的信号句柄只能起一次作用，信号被捕获一次后，信号句柄就会被还原成默认值了。
// 	//	sigaction设置的信号句柄，可以一直有效，值到你再次改变它的设置。
// 	// signal(SIGPIPE, handle_pipe);
// 	struct sigaction newact;
// 	struct sigaction oldact;
// 	newact.sa_handler = handle_pipe;
// 	sigemptyset(&newact.sa_mask);
// 	newact.sa_flags = 0;
// 	newact.sa_flags |= SA_RESTART;
// 	sigaction(SIGPIPE, &newact, &oldact);

// 	return 0;
// }

void SignalHandleKill(int param)
{
	console_warn("SignalHandleKill()\n");
}

void signal_init(void)
{
	signal(SIGQUIT, SignalHandleKill);
	signal(SIGTERM, SignalHandleKill);
	signal(SIGSTOP, SignalHandleKill);
	// signal(SIGINT   ,SignalHandleKill);
	// signal(SIGPIPE, SIG_IGN);
}

int HAL_init(void)
{
	HAL_UART_Init();
	HAL_MCU_Init();
	HAL_IO_Init();
	// HAL_AUDIO_Init();
	return 0;
}
int PAL_Init(void)
{
#if 1

	PAL_VZ_AppInit();
#endif
	PROTOCOL_CR_Init();
	PAL_PROTOCOL_RSU_Init();
	return 0;
}

void wifiInit(void *arg)
{
	uint8_t *wifiSsid = getWiFiSsid();
	uint8_t *wifiPwd = getWiFiPwd();

	uint8_t camNum = getCameraNum();
	VzCamInfoStruct *camInfo = getCameraInfo();

	// 写wifi配置文件
	// echo -e "a\n 292\n" > wpa_supplicant.conf
	system("cd /etc && wr touch wpa_supplicant.conf");

	uint8_t wifiConfCmd[512] = {0};
	sprintf(wifiConfCmd, "cd /etc && wr touch wpa_supplicant.conf && wr echo -e \"ctrl_interface=/var/run/wpa_supplicant\nap_scan=1\n\nnetwork={\n\tssid=\\\"%s\\\"\n\tpsk=\\\"%s\\\"\n}\n\" > /etc/wpa_supplicant.conf", wifiSsid, wifiPwd);
	system(wifiConfCmd);

	uint8_t camIPs[64] = {0};
	uint8_t *camIPsPtr = camIPs;
	for (size_t i = 0; i < camNum; i++)
	{
		sprintf(camIPsPtr, " %s", camInfo[i].VZ_CAM_IP);
		camIPsPtr += strlen(camInfo[i].VZ_CAM_IP) + 1;
	}

	uint8_t wifiCmd[128] = {0};
	sprintf(wifiCmd, "cd /home/Tim/sh && sh start_wifi.sh %s", camIPs);
	int32_t systemRet = system(wifiCmd);

	if (WEXITSTATUS(systemRet) != 1)
	{
		LOG_INFO("WIFI 脚本执行成功");
	}
	else
	{
		LOG_ERROR("WIFI 脚本执行失败");
	};
}

// static void loopAliveLog(uv_timer_t *handler)
// {
// 	LOG_INFO("事件池存活");
// }

int main(T_INT32 argc, T_CHAR **argv)
{
	// 1、console_loop
	// 2、_HAL_AUDIO_CaptureThrea
	// 3、_HAL_UART_RecvThread
	// 以上3个固定占用线程池3个线程
	// 剩下3个自由分配去给其他任务使用
	putenv("UV_THREADPOOL_SIZE=16");

	const char *pidfile = "/var/run/tim.pid";
	uint32_t consoleTh;
	if (PidfileTestRunning(pidfile) != 0)
	{
		return -1;
	}

	PidfileCreate(pidfile);

	chdir("/opt/Tim");
	system("mkdir -p /tmp/updateFirmware");

	log_init("log_all", "./conf/zlog.conf");

	{
		// loop初始化
		initLoop();
	}

	// 读取配置
	load_cfg();

	// uv_thread_t tid;
	// uv_thread_create(&tid, wifiInit, NULL);
	wifiInit(NULL);

	{
		// libuv相关初始化
		laneLoopInit();
		vzCmdInit();
	}

	{
		// 其他零碎的初始化
		initReserveFrame();
		picsQueueInit();
		othersQueueInit();
		sqlCmdQueueInit();
		sql2SocketQueueInit();

		timerQueueInit();

		sql2SocketUvInit();
		halGpsLoopInit();
	}

	{
		// test相关
		// vzAsyncInit();
		test_func();
	}

	{
		// Log测试
		char buf[80];
		getcwd(buf, sizeof(buf));
		LOG_INFO("当前工作目录: %s", buf);
		LOG_FATAL("当前工作目录: %s", buf);
		LOG_DEBUG("当前工作目录: %s", buf);
		LOG_NOTICE("当前工作目录: %s", buf);
		LOG_ERROR("当前工作目录: %s", buf);
	}

	show_logo();
	{
		// 异常信号处理
		// init_lxf();
		signal(SIGPIPE, SIG_IGN);
		signal(SIGSEGV, handle_sevg);
	}

	{
		// 启动相机相关任务
		if (PAL_Init() < 0)
		{
			LOG_ERROR("FAL_init() errorr");
			return -1;
		}
	}

	{
		// 命令初始化
		Console_Init();
	}

	if (HAL_init() < 0)
	{
		LOG_ERROR("HAL_init() error");
		return -1;
	}
	LOG_INFO("HAL Init Done!");
	{
		// 机器人业务事件
		laneAppInit();
	}
	{
		// 增加命令交互
		addVzCmd();
	}

	startWatchRemoteCfg();

	// 1、图片包文件块大小 2048
	// 2、车牌重复间隔 10s
	// 3、千寻的认证记得打开
	uv_work_t *console_work_req = (uv_work_t *)malloc(sizeof(uv_work_t));
	uv_queue_work(getLoop(), console_work_req, Console_Loop, NULL);

	uv_work_t sql_req;
	uv_queue_work(getLoop(), &sql_req, startSqlLoop, closePicDb);

	/**图片删除线程**/
	uv_work_t delete_pic_req;
	uv_queue_work(getPicDeleteLoop(), &delete_pic_req, startPicDeleteWork, NULL);

	// uv_sleep(5* 1000); //等待wifi初始化成功.
	{
		// 硬件初始化相关的都放这里
		gps_init();
		getQxAddrInfoAndConnect(NULL);
	}
	uv_run(getLoop(), UV_RUN_DEFAULT);

	return 0; //保活
}

// sql测试代码
// gps_t gps;
// memcpy(gps.gps_gngga_data, "$GNGGA,005517.00,2256.77897,N,11315.35324,E,5,12,0.58,5.0,M,-5.5,M,11.0,0901*41", MINMEA_MAX_LENGTH);
// memcpy(gps.gps_gnrmc_data, "$GNRMC,030420.00,A,2308.09198,N,11320.35858,E,0.010,,080821,,,F,V*16", MINMEA_MAX_LENGTH);

// uint8_t timeee[6] = {0x21, 0x09, 0x01, 0x11, 0x23, 0x31};
// uint8_t timeee1[6] = {0};
// uint8_t timeee2[6] = {0};
// time_bcd(timeee1);
// time_bcd(timeee2);
// openPicDb();
// createPicDB();
// insertPicDb(
// 	"000C292E3EF7FFFF123456762109030946339E0201",
// 	1,
// 	2,
// 	timeee,
// 	gps,
// 	false);

// insertPicDb(
// 	"000C292E3EF7FFFF123456762109030946339E0202",
// 	1,
// 	2,
// 	timeee1,
// 	gps,
// 	true);

// insertPicDb(
// 	"000C292E3EF7FFFF123456762109030946339E0203",
// 	1,
// 	2,
// 	timeee2,
// 	gps,
// 	true);

// LOG_NOTICE("筛选大图");
// selectPicDb(true);
// LOG_NOTICE("筛选小图");
// selectPicDb(false);

// LOG_NOTICE("更新删除标识位");
// updatePicRowAfterDelete("000C292E3EF7FFFF123456762109030946339E0202");

// LOG_NOTICE("更新上传标识位");
// updatePicRowAfterUpload("000C292E3EF7FFFF123456762109030946339E0202");

// LOG_NOTICE("删除一星期前的数据");
// deletePicRows();

// closePicDb();